#include<netinet/in.h> // sockaddr_in
#include<sys/types.h>  // socket
#include<sys/socket.h> // socket
#include<stdio.h>    // printf
#include<stdlib.h>   // exit
#include<string.h>   // bzero

#define SERVER_PORT 8000
#define LENGTH_OF_LISTEN_QUEUE 20
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512
#define MAX 10000000

int main(void)
{
    // 声明并初始化一个服务器端的socket地址结构
    struct sockaddr_in server_addr;
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htons(INADDR_ANY);
    server_addr.sin_port = htons(SERVER_PORT);
    SSL_CTX *ctx;
    
  
    SSL_library_init();
    OpenSSL_add_all_algorithms();
    SSL_load_error_strings();
    ctx = SSL_CTX_new(SSLv23_server_method());
    if (ctx == NULL) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
    if (SSL_CTX_use_certificate_file(ctx, argv[3], SSL_FILETYPE_PEM) <= 0) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
    if (SSL_CTX_use_PrivateKey_file(ctx, argv[4], SSL_FILETYPE_PEM) <= 0){
        ERR_print_errors_fp(stdout);
        exit(1);
    }
    if (!SSL_CTX_check_private_key(ctx)) {
        ERR_print_errors_fp(stdout);
        exit(1);
    }
    
    
    // 创建socket，若成功，返回socket描述符
    int server_socket_fd = socket(PF_INET, SOCK_STREAM, 0);
    if(server_socket_fd < 0)
    {
        perror("Create Socket Failed:");
        exit(1);
    }
    int opt = 1;
    setsockopt(server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    
    // 绑定socket和socket地址结构
    if(-1 == (bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr))))
    {
        perror("Server Bind Failed:");
        exit(1);}
      
    // socket监听
    if(-1 == (listen(server_socket_fd, LENGTH_OF_LISTEN_QUEUE)))
    {
        perror("Server Listen Failed:");
        exit(1);}
    while(1)
    {
        SSL *ssl;
        // 定义客户端的socket地址结构
        struct sockaddr_in client_addr;
        socklen_t client_addr_length = sizeof(client_addr);
        int new_server_socket_fd = accept(server_socket_fd, (struct sockaddr*)&client_addr,&client_addr_length);
        if(new_server_socket_fd < 0)
        {
            perror("Server Accept Failed:");
            break;
         
        }
            
        ssl = SSL_new(ctx);
        SSL_set_fd(ssl, new_server_socket_fd);
            
        if (SSL_accept(ssl) == -1) {
            perror("accept");
            close(new_fd);
            break;
            }
        // recv函数接收数据到缓冲区buffer中
        char buffer[BUFFER_SIZE];
        bzero(buffer, BUFFER_SIZE);
        if(recv(new_server_socket_fd, buffer, BUFFER_SIZE, 0) < 0)
        {
            perror("Server Recieve Data Failed:");
            break;
        }
        int len = SSL_read(ssl, buffer, MAXBUF);
            
        if (len > 0)
            printf("接收消息成功:'%s'，共%d个字节的数据\n", buffer, len);
        else
            printf("消息接收失败！错误代码是%d，错误信息是'%s'\n",errno, strerror(errno));
            
        // 然后从buffer(缓冲区)拷贝到file_name中
        char file_name[FILE_NAME_MAX_SIZE+1];
        bzero(file_name, FILE_NAME_MAX_SIZE+1);
        strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));
        printf("filename:%s\n", file_name);
        // 打开文件并读取文件数据
        FILE *fp = fopen(file_name, "r");
        if(NULL == fp)
        {
            printf("File:%s Not Found\n", file_name);}
        else
        {
            //printf("buffer:%s\n",buffer);//buffer为filename
            
            char *argv[]={"wc","-w",file_name,0};
            execvp( "wc" ,argv);
            
            fclose(fp);
            SSL_shutdown(ssl);
            SSL_free(ssl);}
            // 关闭与客户端的连接
            close(new_server_socket_fd);
            }
    // 关闭监听用的socket
    close(server_socket_fd);
    SSL_CTX_free(ctx);
    return 0;
}
